package com.mspbots.rule.exceptions.attendance;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.mspbots.cw.request.AttendanceDTO;
import com.mspbots.cw.request.TenantUserConfigurationDTO;
import com.mspbots.cw.request.TenantUserDTO;
import lombok.extern.slf4j.Slf4j;
import org.jeasy.rules.annotation.Action;
import org.jeasy.rules.annotation.Condition;
import org.jeasy.rules.annotation.Fact;
import org.jeasy.rules.annotation.Rule;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName com.mspbots.rule.exceptions.attendance.BeforeWorkStart
 * @Description TODO
 * @Author Jun
 * @Date 2019/9/17 10:28
 * @Version 1.0
 **/
@Slf4j
@Rule(name = "BeforeWorkStart",
        description = "Dear [user], it is [current time][Timezone label], " +
                "you are scheduled to start working at [scheduled starting time]. " +
                "Please log in with [Software_of_time_keeping] when you started to work.")
public class BeforeWorkStart extends AttendanceBaseRule {

    private LocalDateTime workDateTimeUTC;
    private TenantUserDTO tenantUserDTO;

    @Condition
    public boolean condition(@Fact(FACT) TenantUserConfigurationDTO tenantUserConfigurationDTO) {

        try {
            if (!setUserMapping(tenantUserConfigurationDTO.getTenantUserId())
                    || super.checkDayMessage(tenantUserConfigurationDTO.getTenantUserId())) {
                return false;
            }

            LocalTime startTime = getTodayTime("startTime");
            if (startTime == null) {
                log.debug("tenant user [{}] startTime is null [{}]",
                        tenantUserConfigurationDTO.getTenantUserId(), LocalDateTime.now());
                return false;
            }

            workDateTimeUTC = LocalDateTime.of(LocalDateTime.now().plusHours(tz).toLocalDate(), startTime).minusHours(tz);

            JsonNode params = JSONUtil.isNull(this.tenantRuleDTO.getRuleParams()) ?
                    this.tenantRuleDTO.getSysParams() : this.tenantRuleDTO.getRuleParams();
            log.debug("BeforeWorkStart_{} {} {} {}", tenantUserConfigurationDTO.getTenantUserId(), startTime, workDateTimeUTC, params.get("Mins").asInt());
            // check if now is between x-m and y . eg：
            // now is 7：12 , is before 7:45 then return false
            // now is 8:02 , is After 8:00 then return false
            if (LocalDateTime.now().isBefore(workDateTimeUTC.minusMinutes(params.get("Mins").asInt()))
                    || LocalDateTime.now().isAfter(workDateTimeUTC)) {
                return false;
            }


            // check if user has BOD
            AttendanceDTO attendanceDTO = getAttendance(Map.of("tenantId", tenantUserConfigurationDTO.getTenantId(),
                    "userId", tenantUserConfigurationDTO.getTenantUserId(), "type", "IN"));

            log.debug("BeforeWorkStart_attendanceDTO_{} {} ", tenantUserConfigurationDTO.getTenantUserId(), attendanceDTO);
            //if user has BOD in 12 hour. eg： work at 8:00, BOD at 7:20
            if (!ObjectUtils.isEmpty(attendanceDTO) && in12Hour(attendanceDTO)) {
                return false;
            }

            tenantUserDTO = tenantUserService.findById(tenantUserMappingDTO.getTenantUserId());
            log.debug("BeforeWorkStart_attendanceDTO_{} {} ", tenantUserConfigurationDTO.getTenantUserId(), tenantUserDTO.getSoftware());
            if ("tsheet".equalsIgnoreCase(tenantUserDTO.getSoftware())) {
                return false;
            }

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("BeforeWorkStart error : [{}] ", tenantUserConfigurationDTO.getTenantUserId());
        }
        return false;
    }

    @Action
    public void action(@Fact(FACT) TenantUserConfigurationDTO tenantUserConfigurationDTO) {
        String template = StringUtils.isEmpty(this.tenantRuleDTO.getTemplate()) ? this.tenantRuleDTO.getSysTemplate()
                : this.tenantRuleDTO.getTemplate();

        String now = LocalDateTime.now().plusHours(tz).format(DateTimeFormatter.ofPattern("MM/dd HH:mm"));
        Map<String, Object> params = new HashMap<>(16);
        params.put("USER", tenantUserMappingDTO.getFirstName());
        params.put("Now", styleParam(now));
        params.put("TimeZone", styleParam(tzStr));
        params.put("StartTime", styleParam(workDateTimeUTC.plusHours(tz).format(DateTimeFormatter.ofPattern("MM/dd HH:mm"))));
        if (StringUtils.isEmpty(tenantUserDTO.getSoftware())) {
            params.put("Software_of_time_keeping", styleParam("mspbots"));
        } else {
            params.put("Software_of_time_keeping", styleParam(tenantUserDTO.getSoftware()));
        }
        String message = StrUtil.format(template, params);

        String suffixMessage = new StringBuilder()
                .append("--")
                .append("<span style='color:#999d9c;font-size:10px;'>")
                .append(suffixUserName())
                .append("[")
                .append(now)
                .append(" ").append(tzStr)
                .append("]")
                .append("</span>").toString();

        messages.setMessage(message + "<br>" + suffixEscalation() + suffixMessage);
        messages.setBusinessType("attendance");
        insertMessage(messages);
    }


}
